package com.experiment05;

import com.experiment05.resource.DatabaseUtils;
import com.experiment05.entity.College;
import com.experiment05.entity.Student;
import com.experiment05.entity.Teacher;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class Test {
    //非空学生集合
    private static final List<Student> students1 = DatabaseUtils.listStudents();
    //空学生集合
    private static final List<Student> students2 = new ArrayList<>();

    public static void main(String[] args) {
        System.out.println("一、基于给定学生，获取学生的导师的所在学院名称:");
        System.out.println("学生存在：" + getCollegeName(students1.get(0)));
        System.out.println("学生不存在：" + getCollegeName(null));
        System.out.println();

        System.out.println("二、基于给定学生及教师姓名，判断是否为给定学生的指导教师:");
        System.out.println("学生老师匹配：" + isTeacher(DatabaseUtils.listStudents().get(0), "吕惠玲"));
        System.out.println("学生老师不匹配：" + isTeacher(DatabaseUtils.listStudents().get(0), "曾志优"));
        System.out.println("学生为空：" + isTeacher(null, "曾志优"));
        System.out.println();

        System.out.println("三、基于给定学生集合，学生编号，实现获取学生的导师的所在学院名称:");
        System.out.println("学生集合不空，编号匹配：" + getCollegeName(students1,201002));
        System.out.println("学生集合不空，编号不匹配：" + getCollegeName(students1,8888));
        System.out.println("学生集合为空：" + getCollegeName(students2,201002));
        System.out.println();

        System.out.println("四、实现在给定学生集合中查询指定编号学生，如果学生导师编号为指定编号，打印显式导师所在学院名称:");
        System.out.print("学生集合不空，老师匹配：");
        printCollegeName(students1,201001,1001);
        System.out.print("学生集合不空，老师不匹配：");
        printCollegeName(students1,201001,1002);
        System.out.print("学生集合为空：");
        printCollegeName(students2,201001,1001);

    }

    /**
     * 基于给定学生，获取学生的导师的所在学院名称。
     * 任何一项不存在或失败，返回 未知学院
     * @param student
     * @return 学院名字 or 未知学院
     */
    private static String getCollegeName(Student student) {
        return Optional.ofNullable(student)
                //学生为空时，执行map(Student::getTeacher)方法但不执行方法里的函数，返回空容器
                .map(Student::getTeacher)
                //老师为空时，执行map(Teacher::getCollege)方法但不执行方法里的函数，返回空容器
                .map(Teacher::getCollege)
                //学院为空时，执行map(College::getName)方法但不执行方法里的函数，返回空容器
                .map(College::getName)
                //以上只要有一个为空，则最终获得的是一个空容器
                //容器不空，返回学院名字;容器为空，返回默认值"未知学院"
                .orElse("未知学院");
    }

    /**
     * 基于给定学生及教师姓名，判断是否为给定学生的指导教师。
     * 不匹配或不存在，均返回false
     * @param student
     * @param teacherName
     * @return
     */
    private static boolean isTeacher(Student student, String teacherName) {
        //基于可能为空的学生创建容器
        return Optional.ofNullable(student)
                //老师为空时，返回空容器
                .map(Student::getTeacher)
                //以老师名字过滤，无论是否空，过滤结果置于新容器
                .filter(teacher -> teacherName.equals(teacher.getName()))
                .isPresent();
    }

    private static boolean isTeacher2(Student student, String teacherName) {
        //基于可能为空的学生创建容器
        return Optional.ofNullable(student)
                //映射新容器
                .map(Student::getTeacher)
                .map(Teacher::getName)
                //以老师名字过滤，无论是否空，过滤结果置于新容器
                //.filter(name -> teacherName.equals(name))的简写
                .filter(teacherName::equals)
                //根据过滤完后是否为空判断是否匹配
                .isPresent();
    }

    private static boolean isTeacher3(Student student, String teacherName) {
        //基于可能为空的学生创建容器
        return Optional.ofNullable(student)
                //映射新容器
                .map(Student::getTeacher)
                .map(Teacher::getName)
                //容器为空，返回空名字；容器不为空，返回容器中的名字。
                .orElse("")
                .equals(teacherName);
    }





    /**
     * 基于给定学生集合，学生编号，实现获取学生的导师的所在学院名称。
     * 任何一项不存在或失败，返回 未知学院
     * 结合collection stream findFirst()方法实现
     * 可直接通过一条方法链实现
     *
     * @param students
     * @param sNumber
     * @return
     */
    private static String getCollegeName(List<Student> students, int sNumber) {
        //先将学生集合转为流,当学生集合为空是不会报错，转为一个空的集合流
        return students.stream()
                //基于集合流根据学生编号过滤学生
                .filter(student -> student.getNumber() == sNumber)
                //findFirst()取出集合流中的第一个对象，装入容器并返回
                //若集合流为空，则返回空容器
                .findFirst()
                .map(Student::getTeacher)
                .map(Teacher::getCollege)
                .map(College::getName)
                .orElse("未知学院");
    }




    /**
     * 实现在给定学生集合中查询指定编号学生，如果学生导师编号为指定编号，打印显式导师所在学院名称。
     * 任何一项不存在或失败，打印显式 未知学院
     * 结合collection stream findFirst()方法实现
     * 可直接通过一条方法链实现
     *
     * @param students
     * @param sNumber，学生编号
     * @param tNumber，教师编号
     */
    private static void printCollegeName(List<Student> students, int sNumber, int tNumber) {
        //先将学生集合转为流
       students.stream()
               //基于集合流根据学生编号过滤学生
               .filter(student -> student.getNumber() == sNumber)
               .map(Student::getTeacher)
               //基于集合流根据老师编号过滤老师
               .filter(teacher -> teacher.getNumber() == tNumber)
               //findFirst()取出集合流中的第一个对象，装入容器并返回
               //若集合流为空，则返回空容器
               .findFirst()
               .map(Teacher::getCollege)
               .map(College::getName)
               .ifPresentOrElse(System.out::println,() -> {
                   System.out.println("未知学院");
               });
    }

    private static void printCollegeName2(List<Student> students, int sNumber, int tNumber) {
        //先将学生集合转为流
        Teacher teacher = students.stream()
                .filter(student -> student.getNumber() == sNumber)
                .findFirst()
                .map(Student::getTeacher)
                .orElse(null);
        String s = Optional.ofNullable(teacher)
                .filter(t ->t.getNumber() ==tNumber)
                .map(Teacher::getCollege)
                .map(College::getName)
                .orElse( "UNKNOW");
        System.out.println(s);
    }




}